# frozen_string_literal: true

require 'spec_helper'

RSpec.describe Llm::ExplainVulnerabilityService, :saas, feature_category: :vulnerability_management do
  let_it_be(:user) { create(:user) }
  let_it_be_with_reload(:namespace) { create(:group_with_plan, plan: :ultimate_plan) }
  let_it_be(:project) { create(:project, namespace: namespace) }
  let_it_be(:vulnerability) { create(:vulnerability, :with_finding, project: project) }
  let_it_be(:options) { { include_source_code: true } }

  subject { described_class.new(user, vulnerability, options) }

  before do
    stub_feature_flags(openai_experimentation: true)
  end

  describe '#execute' do
    before do
      stub_application_setting(check_namespace_plan: true)
      stub_feature_flags(explain_vulnerability: project, openai_experimentation: true)
      stub_licensed_features(ai_features: true, security_dashboard: true)

      namespace.update!(
        experiment_features_enabled: true,
        third_party_ai_features_enabled: true
      )

      allow(Llm::CompletionWorker).to receive(:perform_async).with(
        user.id,
        vulnerability.id,
        "Vulnerability",
        :explain_vulnerability,
        options
      )
    end

    context 'when the user is permitted to view the vulnerability' do
      before do
        namespace.add_developer(user)
      end

      let(:resource) { vulnerability }
      let(:action_name) { :explain_vulnerability }
      let(:content) { 'Explain vulnerability' }

      it_behaves_like 'service not emitting message for user prompt'
      it_behaves_like 'completion worker sync and async'
      it_behaves_like 'llm service does not cache user request'

      context 'when feature flag is disabled' do
        before do
          stub_feature_flags(explain_vulnerability: false)
        end

        it 'returns an error' do
          expect(subject.execute).to be_error

          expect(Llm::CompletionWorker).not_to have_received(:perform_async)
        end
      end
    end

    context 'when the user is not permitted to view the vulnerability' do
      it 'returns an error' do
        expect(subject.execute).to be_error

        expect(Llm::CompletionWorker).not_to have_received(:perform_async)
      end
    end

    context 'when experimental features are disabled' do
      before do
        project.add_maintainer(user)
        namespace.update!(experiment_features_enabled: false)
      end

      it 'returns an error' do
        result = subject.execute
        expect(result).to be_error

        expect(Llm::CompletionWorker).not_to have_received(:perform_async)
      end
    end
  end
end
